#include "CWebSocketServer.h"

#if defined(WIN32)
#define close  closesocket
#endif

#if defined(LINUX)
#define INVALID_SOCKET -1
#endif

#if defined(WIN32)
#pragma comment(lib, "ws2_32.lib")
#endif

CWebSocketServer::CWebSocketServer()
{
#if defined(_WIN32)
	WORD wVersionRequested;
	WSADATA wsaData;
	wVersionRequested = MAKEWORD(2, 0);

	if (WSAStartup(wVersionRequested, &wsaData) != 0)
	{
		assert(false);
	}

#endif
}
CWebSocketServer::~CWebSocketServer()
{
#if defined(_WIN32)
	WSACleanup();
#endif

}


int CWebSocketServer::Stop()
{
	base::SimpleThread::Stop();
	base::SimpleThread::Join();

	_deinitialize();

	return 0;
}

int CWebSocketServer::_deinitialize()
{
	
	if (_socket != INVALID_SOCKET)
	{
		close(_socket);
		_socket = INVALID_SOCKET;
	}


    for (int i = 0; i < mWebSocketHandlerVector.size(); i++)
    {
        WebsocketHandler* _handler = mWebSocketHandlerVector[i];
        _handler->disconnect();
        delete _handler;
        _handler = NULL;
    }

    mWebSocketHandlerVector.clear();
    std::vector<WebsocketHandler*>().swap(mWebSocketHandlerVector);


	return 0;
}
int  CWebSocketServer::Initialization(int port)
{
	//1. socket
	_socket = socket(AF_INET, SOCK_STREAM, 0);

	if (_socket == INVALID_SOCKET)
	{
		perror("Failed to create server socket!");
		//printf("create socket error: %s(errno: %d)\n", strerror(errno), errno);
		return -1;
	}

	//2.bind
	struct sockaddr_in myaddr;
	myaddr.sin_family = AF_INET;
	myaddr.sin_port = htons(port);
	myaddr.sin_addr.s_addr = INADDR_ANY;

	if (bind(_socket, (struct sockaddr*) &myaddr, sizeof(struct sockaddr)) < 0)
	{
		perror("Failed to bind!");
		printf("bind error: %s(errno: %d)\n", strerror(errno), errno);
		close(_socket);
		return -1;
	}

	//3.listen

	if (listen(_socket, 10) < 0)
	{
		perror("Failed to listen!");
		printf("listen error: %s(errno: %d)\n", strerror(errno), errno);
		close(_socket);
		return -1;
	}

	base::SimpleThread::Start();

	printf("server tcp ok......\n");

	return 0;
}

void CWebSocketServer::Run()
{
	while (true)
	{
		if (base::SimpleThread::IsStop())
		{
			break;
		}

		int max_fd = 0;

		fd_set          rfds;
		struct timeval  to = { 5, 0 };

		FD_ZERO(&rfds);
		FD_SET(_socket, &rfds);

		max_fd = _socket;

		for (int i = 0; i < mWebSocketHandlerVector.size(); i++)
		{
            WebsocketHandler* _handler = mWebSocketHandlerVector[i];

            FD_SET(_handler->m_socket_, &rfds);
            if (_handler->m_socket_ > max_fd)
			{
                max_fd = _handler->m_socket_;
			}
        }


		int res = select(max_fd + 1, &rfds, NULL, NULL, &to);
		if (res < 0)
		{
			break;
		}
		if (res == 0)
		{
			continue;
		}

		if (res > 0)
		{
			printf("server a client......\n");

            for(std::vector<WebsocketHandler*>::iterator iter=mWebSocketHandlerVector.begin(); iter!=mWebSocketHandlerVector.end(); )
            {
                WebsocketHandler* _handler = *iter;

                if (FD_ISSET(_handler->m_socket_, &rfds))
                {
                    int nread = recv(_handler->m_socket_, _handler->getbuff(), BUFFLEN, 0);
                    if (nread <= 0)
                    {
                        //close
                        _handler->disconnect();

                        iter = mWebSocketHandlerVector.erase(iter);

                        delete _handler;
                        _handler = NULL;

                        printf(" peer close....\n");
                    }
                    else
                    {
                        int ret = _handler->process(_handler->m_socket_,nread);
                        if(ret == -5)
                        {
                            //close
                            _handler->disconnect();

                            iter = mWebSocketHandlerVector.erase(iter);

                            delete _handler;
                            _handler = NULL;

                            printf(" peer close....\n");
                        }
                        //int _send = send(_c_socket, buffer, nread, 0);
                        //printf("recv %s\n", mWebSocketHandlerVector[i].getbuff());
                    }
                }
                else
                {
                    iter ++ ;
                }

            }
			
			if (FD_ISSET(_socket, &rfds))
			{
				printf("server a accept......\n");

				struct  sockaddr_in cliaddr;
				socklen_t clilen;
				clilen = sizeof(cliaddr);

                int _csocket_ = accept(_socket, (struct sockaddr *)&cliaddr, &clilen);
                if (_csocket_ == INVALID_SOCKET)
				{
					printf("accept error\n");
					//delete client;
				}
				else
				{
                    WebsocketHandler  *_handler = new WebsocketHandler(_csocket_);
                    assert(_handler != NULL);
                    mWebSocketHandlerVector.push_back(_handler);
				}

			}
		}
	}
}
